//
// Created by richard on 2018-12-25.
//

#include "SimLinearSensor.h"
#ifdef _WIN32
#include <windows.h>
#endif
#ifndef _WIN32

#include <unistd.h>
#endif


/**
 *
 * @param value 传感器初始值
 * @param timeStep 数据更新间隔，默认1秒
 */
SimLinearSensor::SimLinearSensor(uint16_t value, int timeStep) : value(value), timeStep(timeStep) {
    initThread();
}

SimLinearSensor::SimLinearSensor(uint16_t value) : value(value) {
    initThread();
}

void SimLinearSensor::initThread() {
    this->thread = new std::thread(SimLinearSensor::threadFunc, this);
}

void SimLinearSensor::startRaise() {
    this->threadStep = this->step;
    this->isRaise = true;
}

void SimLinearSensor::startRaise(uint16_t step) {
    this->step = step;
    this->startRaise();
}

void SimLinearSensor::raise() {
    value += step;
}

void SimLinearSensor::raise(uint16_t step) {
    this->step = step;
    raise();
}

void SimLinearSensor::startReduce() {
    this->threadStep = step;
    this->isRaise = false;
}

void SimLinearSensor::startReduce(uint16_t step) {
    this->step = step;
    this->startReduce();
}

void SimLinearSensor::reduce() {
    value -= step;
}

void SimLinearSensor::reduce(uint16_t step) {
    this->step = step;
    reduce();
}

void SimLinearSensor::threadFunc(SimLinearSensor *p) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmissing-noreturn"
    while(true){
        sleep(p->timeStep);
        if(p->isRaise){
            p->value += p->threadStep;
        }else{
            p->value -= p->threadStep;
        }
        if(p->backgroundStep > 0 && p->value + p->backgroundStep < p->backgroundMax){
            p->value += p->backgroundStep;
        }
        if(p->backgroundStep < 0 && p->value + p->backgroundStep > p->backgroundMin){
            p->value += p->backgroundStep;
        }
        p->loopCallback();
    }
#pragma clang diagnostic pop
}

void SimLinearSensor::pause() {
    this->threadStep = 0;
}

uint16_t SimLinearSensor::get() {
    return value;
}

void SimLinearSensor::setBackgroundStep(int16_t step) {
    this->backgroundStep = step;
}

void SimLinearSensor::setBackgroundMin(uint16_t min) {
    this->backgroundMin = min;
}

void SimLinearSensor::setBackgroundMax(uint16_t max) {
    this->backgroundMax = max;
}

void SimLinearSensor::setBackgroundTarget(uint16_t target) {
    uint16_t diff = 0;
    if(this->value > target){
        diff = this->value - target;
        this->backgroundStep = -(diff / 10 + 1);
    }else if(this->value < target){
        diff = target - this->value;
        this->backgroundStep = diff/10 + 1;
    }else{
        this->backgroundStep = 0;
    }
}

void SimLinearSensor::setBackgroundTarget(uint16_t target, uint16_t ratio) {
    uint16_t diff = 0;
    if(this->value > target){
        diff = this->value - target;
        this->backgroundStep = -(diff / ratio + 1);
    }else if(this->value < target){
        diff = target - this->value;
        this->backgroundStep = diff/ratio + 1;
    }else{
        this->backgroundStep = 0;
    }
}

